import { createWorker, createScheduler } from 'tesseract.js'
import jsQR from "jsqr"
import { drawVideoToCanvas } from './utils'

export default class HTesseract{
  constructor(onload=null){
    this.interval = 0
    this.stop = false
    this.onload = onload
    this.ocrTimes = []
    this.avgTime = 0
    this.qrTimes = []
    this.qrAvg = 0
    this.workerNum = 4
    this.scheduler = createScheduler();
    this.createWorkers(this.workerNum)
  }

  async createWorkers(num = 4){
    for (let i = 0; i < num; i++) {
      const worker = await createWorker({
        // https://tessdata.projectnaptha.com/4.0.0/eng.traineddata.gz 可以下载语言文件
        langPath: './lang-data',
        // logger: m => console.log(m),
      });
      const lang = 'eng+chi_sim'
      await worker.loadLanguage(lang);
      await worker.initialize(lang);
      this.scheduler.addWorker(worker);
      if (i === 0 && this.onload) {
          this.onload()
      }
    }
  }

  startOcrFromVideo(video, cb){
    let lastTime = Date.now()
    const loop = () => {
      if (!video.readyState && video.videoWidth || video.readyState === video.HAVE_ENOUGH_DATA) {
        const workerNum = this.scheduler.getNumWorkers()
        if (workerNum && this.scheduler.getQueueLen() < workerNum) {
          // ocr比较慢，等有worker空闲的时候才执行
          this.doOCR(video, cb)
        }
        const now = Date.now()
        if (now - lastTime > Math.max(500, this.qrAvg * 2)) {
          // 500ms一次就够了
          lastTime = now
          this.doQrcode(video, cb)
        }
      }
      if (!this.stop) {
        requestAnimationFrame(loop)
      }
    }
    this.stop = false
    loop()
  }

  stopOcrFromVideo() {
    this.stop = true
  }

  async doOCR(video, cb){
    const start = Date.now();
    const [canvas, _] = drawVideoToCanvas(video, 200, true)
    const { data: { text } } = await this.scheduler.addJob('recognize', canvas);
    const end = Date.now()
    this.ocrTimes.push(end - start)
    if (this.ocrTimes.length > 10) {
      this.ocrTimes.splice(0, 1)
    }
    this.avgTime = parseInt(this.ocrTimes.reduce((p, c) => p + c, 0) / this.ocrTimes.length)
    cb(text, 'ocr', canvas)
  }

  async doQrcode(video, cb){
    // todo 这个放到web worker 里执行
    const start = Date.now()
    const width = video.videoWidth
    const height = video.videoHeight
    const [_, ctx] = drawVideoToCanvas(video)
    const imageData = ctx.getImageData(0, 0, width, height)

    const code = jsQR(imageData.data, width, height, {
      inversionAttempts: "dontInvert",
    })
    this.qrTimes.push(Date.now() - start)
    if (this.qrTimes.length > 10) {
      this.qrTimes.splice(0, 1)
    }
    this.qrAvg = parseInt(this.qrTimes.reduce((p, c) => p + c, 0) / this.qrTimes.length)
    if (code) {
      // code.location 是识别到的二维码在图片中的位置
      // drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
      // drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58");
      // drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58");
      // drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58");
      // console.log(code.data);
      cb(code.data, 'qrcode')
    }
  }
}